package com.zyc.auto;

import com.zyc.pojo.Table;
import com.zyc.util.HappyUtil;

import java.io.*;
import java.util.List;

/**
 * 作者：RWdaze
 * 时间：2021/1/28 13:58
 */
public class AutoService {
    /**
     * 目标文件夹
     */
    private final String targetPath;
    /**
     * 目标包名
     */
    private final String targetPackage;

    /**
     * 构造函数，用来初始化一些属性
     */
    public AutoService() {
        targetPath = HappyUtil.properties.getProperty("targetPath");
        targetPackage = HappyUtil.properties.getProperty("namespace");
    }

    /**
     * 生成Service文件的函数入口
     *
     * @throws IOException 写入文件错误
     */
    public void start() throws IOException {
        //获取目标数据库中的所有表名
        List<Table> tableList = HappyUtil.getTableList();
        //遍历所有表名
        for (Table table : tableList) {
            //根据每张表，获取表中所有的字段
            // 生成Service接口
            produceService(table);
            // 生成ServiceImpl
            produceServiceImpl(table);
            // 生成Cache接口
            produceCache(table);
            // 生成CacheImpl
            produceCacheImpl(table);
        }
    }

    /**
     * 根据传入的表，在对应的目标目录下面生成相应的Service接口文件
     *
     * @param table 需要生成的表对象
     * @throws IOException 文件写入错误
     */
    private void produceService(Table table) throws IOException {
        //获取对应类的名字
        String pojoName = table.getTableUpperCamelName();
        //获取对应表的小驼峰名字
        String tableName = table.getTableLowerCamelName();
        //获取对应表的主键类型
        String primaryKeyType = table.getPrimaryKey().getJavaType();
        //获取对应表的主键小驼峰
        String primaryKey = table.getPrimaryKey().getPropertyLowerCamelName();
        //获取目标文件夹路径
        String path = targetPath + "\\service\\" + pojoName + "Service.java";
        //如果目标文件夹不存在，则创建目录
        File addHtmlDir = new File(targetPath + "\\service");
        if (!addHtmlDir.exists() && !addHtmlDir.mkdirs()) {
            return;
        }
        FileOutputStream fos = new FileOutputStream(path);
        OutputStreamWriter osw = new OutputStreamWriter(fos);
        BufferedWriter bw = new BufferedWriter(osw);
        //就一点，就不分方法了。
        bw.write("package " + targetPackage + ".service;\n" +
                "import com.github.pagehelper.PageInfo;\n" +
                "import " + targetPackage + ".pojo." + pojoName + ";\n" +
                "import java.util.List;\n" +
                "public interface " + pojoName + "Service {\n" +
                "PageInfo<" + pojoName + "> selectByCondition(" + pojoName + " " + tableName + ", String page, String limit);\n" +
                "List<" + pojoName + "> selectByCondition(" + pojoName + " " + tableName + ");\n" +
                pojoName + " selectById(" + primaryKeyType + " " + primaryKey + ");\n" +
                "int insert(" + pojoName + " " + tableName + ");\n" +
                "int update(" + pojoName + " " + tableName + ");\n" +
                "int delete(String id);\n" +
                "}");

        //写入结束
        bw.flush();
        System.out.println(path);
        HappyUtil.closeAll(bw, osw, fos);
    }

    /**
     * 根据传入的表，在对应的目标目录下面生成相应的ServiceImpl实现类文件
     *
     * @param table 需要生成的表对象
     * @throws IOException 文件写入错误
     */
    private void produceServiceImpl(Table table) throws IOException {
        //获取对应类的名字
        String pojoName = table.getTableUpperCamelName();
        //获取对应表的小驼峰名字
        String tableName = table.getTableLowerCamelName();
        //获取对应表的主键类型
        String primaryKeyType = table.getPrimaryKey().getJavaType();
        //获取对应表的主键小驼峰
        String primaryKey = table.getPrimaryKey().getPropertyLowerCamelName();
        //获取目标文件夹路径
        String path = targetPath + "\\service\\impl\\" + pojoName + "ServiceImpl.java";
        //如果目标文件夹不存在，则创建目录
        File addHtmlDir = new File(targetPath + "\\service\\impl");
        if (!addHtmlDir.exists() && !addHtmlDir.mkdirs()) {
            return;
        }
        FileOutputStream fos = new FileOutputStream(path);
        OutputStreamWriter osw = new OutputStreamWriter(fos);
        BufferedWriter bw = new BufferedWriter(osw);
        //就一点，就不分方法了。
        bw.write("package " + targetPackage + ".service.impl;\n" +
                "import com.github.xiaolyuh.annotation.*;\n" +
                "import com.github.pagehelper.PageHelper;\n" +
                "import com.github.pagehelper.PageInfo;\n" +
                "import " + targetPackage + ".mapper." + pojoName + "Mapper;\n" +
                "import " + targetPackage + ".pojo." + pojoName + ";\n" +
                "import " + targetPackage + ".service." + pojoName + "Service;\n" +
                "import lombok.extern.slf4j.Slf4j;\n" +
                "import org.springframework.stereotype.Service;\n" +
                "import javax.annotation.Resource;\n" +
                "import java.util.concurrent.TimeUnit;\n" +
                "import java.util.ArrayList;\n" +
                "import java.util.List;\n" +
                "@Service\n" +
                "@Slf4j\n" +
                "public class " + pojoName + "ServiceImpl implements " + pojoName + "Service {\n" +
                "@Resource\n" +
                "private " + pojoName + "Mapper " + tableName + "Mapper;\n" +
                "@Override\n" +
                "public PageInfo<" + pojoName + "> selectByCondition(" + pojoName + " " + tableName + ", String page, String limit) {\n" +
                "PageHelper.startPage(Integer.parseInt(page),Integer.parseInt(limit));\n" +
                "List<" + pojoName + "> list = " + tableName + "Mapper.selectByCondition(" + tableName + ");\n" +
                "return new PageInfo<>(list);}\n" +
                "@Override\n" +
                "public List<" + pojoName + "> selectByCondition(" + pojoName + " " + tableName + ") {\n" +
                "return " + tableName + "Mapper.selectByCondition(" + tableName + ");}\n" +
                "@Override\n" +
                "@Cacheable(value = \"" + tableName + ":selectById\",\n" +
                "depict = \"" + tableName + "的ID查询缓存\",\n" +
                "key = \"#" + primaryKey + "\",\n" +
                "firstCache = @FirstCache(expireTime = 2, timeUnit = TimeUnit.SECONDS),\n" +
                "secondaryCache = @SecondaryCache(expireTime = 120, preloadTime = 24, forceRefresh = true,\n" +
                "isAllowNullValue = true, magnification = 60, timeUnit = TimeUnit.SECONDS))\n" +
                "public " + pojoName + " selectById(" + primaryKeyType + " " + primaryKey + ") {\n" +
                "return " + tableName + "Mapper.selectById(" + primaryKey + ");}\n" +
                "@Override\n" +
                "public int insert(" + pojoName + " " + tableName + ") {\n" +
                "return " + tableName + "Mapper.insertOne(" + tableName + ");}\n" +
                "@Override\n" +
                "@CacheEvict(value = \"" + tableName + ":selectById\", key = \"#" + tableName + "." + primaryKey + "\")\n" +
                "public int update(" + pojoName + " " + tableName + ") {\n" +
                "return " + tableName + "Mapper.update(" + tableName + ");}\n" +
                "@Override\n" +
                "@CacheEvict(value = \"" + tableName + ":selectById\", key = \"#" + tableName + "." + primaryKey + "\")\n" +
                "public int delete(String id) {\n" +
                "return " + tableName + "Mapper.deleteOne(id);}\n" +
                "}");

        //写入结束
        bw.flush();
        System.out.println(path);
        HappyUtil.closeAll(bw, osw, fos);
    }

    private void produceCache(Table table) throws IOException {
        //获取对应类的名字
        String pojoName = table.getTableUpperCamelName();
        //获取对应表的小驼峰名字
        String tableName = table.getTableLowerCamelName();
        //获取对应表的主键类型
        String primaryKeyType = table.getPrimaryKey().getJavaType();
        //获取对应表的主键小驼峰
        String primaryKey = table.getPrimaryKey().getPropertyLowerCamelName();
        //获取目标文件夹路径
        String path = targetPath + "\\cache\\" + pojoName + "Cache.java";
        //如果目标文件夹不存在，则创建目录
        File addHtmlDir = new File(targetPath + "\\cache");
        if (!addHtmlDir.exists() && !addHtmlDir.mkdirs()) {
            return;
        }
        FileOutputStream fos = new FileOutputStream(path);
        OutputStreamWriter osw = new OutputStreamWriter(fos);
        BufferedWriter bw = new BufferedWriter(osw);
        //就一点，就不分方法了。
        bw.write("package " + targetPackage + ".cache;\n" +
                "import " + targetPackage + ".pojo." + pojoName + ";\n" +
                "import java.util.List;\n" +
                "import java.util.concurrent.TimeUnit;\n" +
                "public interface " + pojoName + "Cache {\n" +
                "    List<" + pojoName + "> selectByCondition(" + pojoName + " " + tableName + ");\n" +
                "    " + pojoName + " selectByOne(" + pojoName + " " + tableName + ");\n" +
                "    List<" + pojoName + "> selectByOrder(" + pojoName + " " + tableName + ");\n" +
                "    List<" + pojoName + "> selectAll();\n" +
                "    " + pojoName + " selectById(" + primaryKeyType + " " + primaryKey + ");\n" +
                "    List<" + pojoName + "> simpleSelectByCondition(" + pojoName + " " + tableName + ");\n" +
                "    " + pojoName + " simpleSelectByOne(" + pojoName + " " + tableName + ");\n" +
                "    List<" + pojoName + "> simpleSelectAll();\n" +
                "    " + pojoName + " simpleSelectById(" + primaryKeyType + " " + primaryKey + ");\n" +
                "    int insert(List<" + pojoName + "> list);\n" +
                "    int insertOne(" + pojoName + " " + tableName + ");\n" +
                "    int update(" + pojoName + " " + tableName + ");\n" +
                "    int delete(String[] ids);\n" +
                "    int deleteOne(String id);\n" +
                "}\n");
        //写入结束
        bw.flush();
        System.out.println(path);
        HappyUtil.closeAll(bw, osw, fos);
    }

    private void produceCacheImpl(Table table) throws IOException {
        //获取对应类的名字
        String pojoName = table.getTableUpperCamelName();
        //获取对应表的小驼峰名字
        String tableName = table.getTableLowerCamelName();
        //获取对应表的主键类型
        String primaryKeyType = table.getPrimaryKey().getJavaType();
        //获取对应表的主键小驼峰
        String primaryKey = table.getPrimaryKey().getPropertyLowerCamelName();
        //获取目标文件夹路径
        String path = targetPath + "\\cache\\impl\\" + pojoName + "CacheImpl.java";
        //如果目标文件夹不存在，则创建目录
        File addHtmlDir = new File(targetPath + "\\cache\\impl");
        if (!addHtmlDir.exists() && !addHtmlDir.mkdirs()) {
            return;
        }
        FileOutputStream fos = new FileOutputStream(path);
        OutputStreamWriter osw = new OutputStreamWriter(fos);
        BufferedWriter bw = new BufferedWriter(osw);
        //就一点，就不分方法了。
        bw.write("package " + targetPackage + ".cache.impl;\n" +
                "import com.github.xiaolyuh.annotation.CacheEvict;\n" +
                "import com.github.xiaolyuh.annotation.Cacheable;\n" +
                "import com.github.xiaolyuh.annotation.FirstCache;\n" +
                "import com.github.xiaolyuh.annotation.SecondaryCache;\n" +
                "import " + targetPackage + ".cache." + pojoName + "Cache;\n" +
                "import " + targetPackage + ".mapper." + pojoName + "Mapper;\n" +
                "import " + targetPackage + ".pojo." + pojoName + ";\n" +
                "import org.springframework.stereotype.Component;\n" +
                "import javax.annotation.Resource;\n" +
                "import java.util.List;\n" +
                "import java.util.concurrent.TimeUnit;\n" +
                "@Component\n" +
                "public class " + pojoName + "CacheImpl implements " + pojoName + "Cache {\n" +
                "    @Resource\n" +
                "    private " + pojoName + "Mapper " + tableName + "Mapper;\n" +
                "    @Override\n" +
                "    public List<" + pojoName + "> selectByCondition(" + pojoName + " " + tableName + ") {\n" +
                "        return " + tableName + "Mapper.selectByCondition(" + tableName + ");\n" +
                "    }\n" +
                "    @Override\n" +
                "    public " + pojoName + " selectByOne(" + pojoName + " " + tableName + ") {\n" +
                "        return " + tableName + "Mapper.selectByOne(" + tableName + ");\n" +
                "    }\n" +
                "    @Override\n" +
                "    public List<" + pojoName + "> selectByOrder(" + pojoName + " " + tableName + ") {\n" +
                "        return " + tableName + "Mapper.selectByOrder(" + tableName + ");\n" +
                "    }\n" +
                "    @Override\n" +
                "    public List<" + pojoName + "> selectAll() {\n" +
                "        return " + tableName + "Mapper.selectAll();\n" +
                "    }\n" +
                "    @Override\n" +
                "    @Cacheable(value = \"" + tableName + ":selectById\",\n" +
                "            depict = \"" + tableName + "的ID查询缓存\",\n" +
                "            key = \"#" + primaryKey + "\",\n" +
                "            firstCache = @FirstCache(expireTime = 2, timeUnit = TimeUnit.SECONDS),\n" +
                "            secondaryCache = @SecondaryCache(expireTime = 120, preloadTime = 24, forceRefresh = true,\n" +
                "                    isAllowNullValue = true, magnification = 15, timeUnit = TimeUnit.SECONDS))\n" +
                "    public " + pojoName + " selectById(" + primaryKeyType + " " + primaryKey + ") {\n" +
                "        return " + tableName + "Mapper.selectById(" + primaryKey + ");\n" +
                "    }\n" +
                "    @Override\n" +
                "    public List<" + pojoName + "> simpleSelectByCondition(" + pojoName + " " + tableName + ") {\n" +
                "        return " + tableName + "Mapper.simpleSelectByCondition(" + tableName + ");\n" +
                "    }\n" +
                "    @Override\n" +
                "    public " + pojoName + " simpleSelectByOne(" + pojoName + " " + tableName + ") {\n" +
                "        return " + tableName + "Mapper.simpleSelectByOne(" + tableName + ");\n" +
                "    }\n" +
                "    @Override\n" +
                "    public List<" + pojoName + "> simpleSelectAll() {\n" +
                "        return " + tableName + "Mapper.simpleSelectAll();\n" +
                "    }\n" +
                "    @Override\n" +
                "    public " + pojoName + " simpleSelectById(" + primaryKeyType + " " + primaryKey + ") {\n" +
                "        return " + tableName + "Mapper.simpleSelectById(" + primaryKey + ");\n" +
                "    }\n" +
                "    @Override\n" +
                "    public int insert(List<" + pojoName + "> list) {\n" +
                "        return " + tableName + "Mapper.insert(list);\n" +
                "    }\n" +
                "    @Override\n" +
                "    public int insertOne(" + pojoName + " " + tableName + ") {\n" +
                "        return " + tableName + "Mapper.insertOne(" + tableName + ");\n" +
                "    }\n" +
                "    @Override\n" +
                "    @CacheEvict(value = \"" + tableName + ":selectById\", key = \"#" + tableName + "." + primaryKey + "\")\n" +
                "    public int update(" + pojoName + " " + tableName + ") {\n" +
                "        return " + tableName + "Mapper.update(" + tableName + ");\n" +
                "    }\n" +
                "    @Override\n" +
                "    public int delete(String[] ids) {\n" +
                "        return " + tableName + "Mapper.delete(ids);\n" +
                "    }\n" +
                "    @Override\n" +
                "    @CacheEvict(value = \"" + tableName + ":selectById\", key = \"#id\")\n" +
                "    public int deleteOne(String id) {\n" +
                "        return " + tableName + "Mapper.deleteOne(id);\n" +
                "    }\n" +
                "}");
        //写入结束
        bw.flush();
        System.out.println(path);
        HappyUtil.closeAll(bw, osw, fos);
    }
}
